<template>
  <div class="digital-human-container" ref="containerRef">
    <canvas ref="canvasRef" class="digital-human-canvas"></canvas>
    
    <div v-if="loading" class="loading-overlay">
      <div class="loading-spinner">
        <div class="spinner"></div>
        <p>数字人加载中...</p>
      </div>
    </div>
    
    <div v-if="error" class="error-overlay">
      <div class="error-message">
        <el-icon><Warning /></el-icon>
        <p>{{ error }}</p>
        <el-button @click="retryLoad" type="primary">重试</el-button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
import { ElIcon, ElButton } from 'element-plus'
import { Warning } from '@element-plus/icons-vue'

// 定义组件属性
const props = defineProps({
  // 表情状态: 'neutral' | 'smile' | 'concern' | 'listening'
  expression: {
    type: String,
    default: 'neutral'
  },
  // 动作状态: 'idle' | 'gesture1' | 'gesture2' | 'thinking'
  action: {
    type: String,
    default: 'idle'
  },
  // 是否正在说话（影响唇动效果）
  isSpeaking: {
    type: Boolean,
    default: false
  },
  // 语音文本（用于唇动同步）
  speechText: {
    type: String,
    default: ''
  },
  // 是否显示数字人
  visible: {
    type: Boolean,
    default: true
  }
})

// 定义事件
const emit = defineEmits([
  'load',      // 数字人加载完成
  'error',     // 加载错误
  'animation-end' // 动画播放完成
])

// 响应式数据
const containerRef = ref(null)
const canvasRef = ref(null)
const loading = ref(true)
const error = ref('')
const renderer = ref(null)
const scene = ref(null)
const camera = ref(null)
const digitalHuman = ref(null)
const animationMixer = ref(null)
const currentExpression = ref('neutral')
const currentAction = ref('idle')
const speakingInterval = ref(null)

// 表情和动作映射
const expressionMap = {
  neutral: 'neutral_expression',
  smile: 'smile_expression',
  concern: 'concern_expression',
  listening: 'listening_expression'
}

const actionMap = {
  idle: 'idle_animation',
  gesture1: 'gesture_1_animation',
  gesture2: 'gesture_2_animation',
  thinking: 'thinking_animation'
}

// 初始化数字人
const initDigitalHuman = async () => {
  try {
    loading.value = true
    error.value = ''
    
    // 模拟加载3D库（实际项目中会使用three.js等库）
    await load3DLibrary()
    
    // 初始化渲染器
    initRenderer()
    
    // 初始化场景
    initScene()
    
    // 初始化相机
    initCamera()
    
    // 加载数字人模型
    await loadDigitalHumanModel()
    
    // 设置光照
    setupLighting()
    
    // 启动渲染循环
    startRenderLoop()
    
    loading.value = false
    emit('load')
  } catch (err) {
    loading.value = false
    error.value = `数字人加载失败: ${err.message}`
    emit('error', err)
  }
}

// 模拟加载3D库
const load3DLibrary = () => {
  return new Promise((resolve) => {
    // 模拟加载时间
    setTimeout(() => {
      resolve()
    }, 1000)
  })
}

// 初始化渲染器
const initRenderer = () => {
  if (!canvasRef.value) return
  
  // 模拟初始化渲染器
  renderer.value = {
    setSize: (width, height) => {
      canvasRef.value.width = width
      canvasRef.value.height = height
    },
    render: () => {
      // 模拟渲染过程
    },
    setPixelRatio: () => {}
  }
  
  // 设置初始尺寸
  const container = containerRef.value
  if (container) {
    renderer.value.setSize(container.clientWidth, container.clientHeight)
  }
}

// 初始化场景
const initScene = () => {
  // 模拟场景初始化
  scene.value = {
    add: () => {},
    remove: () => {}
  }
}

// 初始化相机
const initCamera = () => {
  // 模拟相机初始化
  camera.value = {
    position: { x: 0, y: 0, z: 0 },
    lookAt: () => {}
  }
}

// 加载数字人模型
const loadDigitalHumanModel = () => {
  return new Promise((resolve) => {
    // 模拟模型加载
    setTimeout(() => {
      digitalHuman.value = {
        position: { x: 0, y: 0, z: 0 },
        rotation: { x: 0, y: 0, z: 0 },
        scale: { x: 1, y: 1, z: 1 }
      }
      
      // 模拟动画混合器
      animationMixer.value = {
        clipAction: () => ({
          play: () => {},
          stop: () => {},
          setLoop: () => {},
          clampWhenFinished: false
        }),
        update: () => {}
      }
      
      scene.value.add(digitalHuman.value)
      resolve()
    }, 1500)
  })
}

// 设置光照
const setupLighting = () => {
  // 模拟添加光照
}

// 启动渲染循环
const startRenderLoop = () => {
  const animate = () => {
    requestAnimationFrame(animate)
    
    // 更新动画
    if (animationMixer.value) {
      animationMixer.value.update(0.016) // 模拟60fps
    }
    
    // 渲染场景
    if (renderer.value && scene.value && camera.value) {
      renderer.value.render(scene.value, camera.value)
    }
  }
  
  animate()
}

// 更改表情
const changeExpression = (expression) => {
  if (!digitalHuman.value || currentExpression.value === expression) return
  
  currentExpression.value = expression
  
  // 模拟应用表情
  console.log(`应用表情: ${expression}`)
  
  // 实际项目中会在这里切换数字人的表情纹理或形态目标
  // digitalHuman.value.morphTargetInfluences[expressionIndex] = 1
}

// 更改动作
const changeAction = (action) => {
  if (!animationMixer.value || currentAction.value === action) return
  
  currentAction.value = action
  
  // 停止当前动作
  // currentActionClip.stop()
  
  // 播放新动作
  // const newAction = animationMixer.value.clipAction(actionMap[action])
  // newAction.play()
  
  console.log(`播放动作: ${action}`)
}

// 开始唇动同步
const startLipSync = () => {
  if (speakingInterval.value) return
  
  // 模拟唇动同步
  speakingInterval.value = setInterval(() => {
    // 根据语音输入调整口型
    // 这里会根据语音特征调整口型参数
    console.log('唇动同步中...')
  }, 100)
}

// 停止唇动同步
const stopLipSync = () => {
  if (speakingInterval.value) {
    clearInterval(speakingInterval.value)
    speakingInterval.value = null
  }
  
  // 重置口型到默认状态
  console.log('唇动同步停止')
}

// 重试加载
const retryLoad = () => {
  initDigitalHuman()
}

// 处理窗口大小变化
const handleResize = () => {
  if (!containerRef.value || !renderer.value) return
  
  const width = containerRef.value.clientWidth
  const height = containerRef.value.clientHeight
  
  renderer.value.setSize(width, height)
  
  if (camera.value && typeof camera.value.updateProjectionMatrix === 'function') {
    camera.value.aspect = width / height
    camera.value.updateProjectionMatrix()
  }
}

// 监听属性变化
watch(() => props.expression, (newExpression) => {
  changeExpression(newExpression)
})

watch(() => props.action, (newAction) => {
  changeAction(newAction)
})

watch(() => props.isSpeaking, (isSpeaking) => {
  if (isSpeaking) {
    startLipSync()
  } else {
    stopLipSync()
  }
})

// 组件挂载时初始化
onMounted(() => {
  nextTick(() => {
    initDigitalHuman()
    window.addEventListener('resize', handleResize)
  })
})

// 组件卸载前清理
onBeforeUnmount(() => {
  stopLipSync()
  window.removeEventListener('resize', handleResize)
  
  // 清理资源
  if (renderer.value && renderer.value.dispose === 'function') {
    renderer.value.dispose()
  }
})
</script>

<style scoped>
.digital-human-container {
  position: relative;
  width: 100%;
  height: 100%;
  background: #f0f8ff;
  border-radius: 12px;
  overflow: hidden;
}

.digital-human-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.loading-overlay,
.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.9);
  z-index: 10;
}

.loading-spinner {
  text-align: center;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #e0e0e0;
  border-top: 4px solid #409eff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin: 0 auto 16px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.error-message {
  text-align: center;
  padding: 20px;
}

.error-message .el-icon {
  font-size: 48px;
  color: #f56c6c;
  margin-bottom: 16px;
}

.error-message p {
  margin: 16px 0;
  color: #666;
}
</style>